#pragma once
#include <cstdint>
#include <functional>
#include <limits>

namespace xncc {
namespace types {

    namespace IO_MULTI_MODE {
        enum value : uint8_t
        {
            NO_IO_MULTI = 0,
            EPOLL       = 1,
            POLL        = 2,
            SELECT      = 3
        };

        inline const char* toString(const IO_MULTI_MODE::value type)
        {
            switch (type) {
                case NO_IO_MULTI: return "NO_IO_MULTI";
                case EPOLL: return "EPOLL";
                case POLL: return "POLL";
                case SELECT: return "SELECT";
                default: return "UNKNOWN";
            }
        }
    }  // namespace IO_MULTI_MODE

    using message_id_t    = uint32_t;     // 消息id
    using thread_id_t     = int32_t;      // 线程ID的类型
    using queue_id_t      = int32_t;      // 环形队列的类型
    using queue_size_t    = uint64_t;     // 环形队列的长度类型
    using connection_id_t = uint64_t;     // 连接ID
    using engine_id_t     = thread_id_t;  // 事件引擎类型
    using EventCallback   = std::function<void()>;
    using Task            = EventCallback;
    using timer_id_t      = int64_t;

    constexpr timer_id_t      INVALID_TIMER_ID           = -1;
    constexpr connection_id_t FROM_OTHER_THREAD          = UINT64_MAX;       // 消息来自于其他线程
    constexpr connection_id_t NOT_CONNECTION_ID          = 0;                // 非连接ID
    constexpr uint32_t        MAX_SINGLE_TCP_MESSAGE_LEN = 1 * 1024 * 1024;  // 单条tcp消息的最大长度 超过关闭对端连接

    template <typename T>
    struct queue_size_t_limit
    {
        static constexpr T max()
        {
            static_assert(std::is_same<T, void>::value, "Unsupported type for queue_size_t_limit");
            return T{};
        }
        static constexpr T min()
        {
            static_assert(std::is_same<T, void>::value, "Unsupported type for queue_size_t_limit");
            return T{};
        }

        static constexpr T dft()
        {
            static_assert(std::is_same<T, void>::value, "Unsupported type for queue_size_t_limit");
            return T{};
        }
    };

    constexpr uint32_t MIN_QUEUE_SIZE = 1024;

    template <>
    struct queue_size_t_limit<uint16_t>
    {
        static constexpr uint16_t max() { return std::numeric_limits<int16_t>::max(); }
        static constexpr uint16_t min() { return MIN_QUEUE_SIZE; }
        static constexpr uint16_t dft() { return max() / 2; }
    };

    template <>
    struct queue_size_t_limit<uint32_t>
    {
        static uint32_t max() { return std::numeric_limits<int32_t>::max(); }
        static uint32_t min() { return MIN_QUEUE_SIZE; }

        static constexpr uint32_t dft() { return MIN_QUEUE_SIZE * MIN_QUEUE_SIZE; }
    };

    template <>
    struct queue_size_t_limit<uint64_t>
    {
        static constexpr uint64_t max() { return std::numeric_limits<int64_t>::max(); }
        static constexpr uint64_t min() { return MIN_QUEUE_SIZE; }

        static constexpr uint64_t dft() { return static_cast<uint64_t>(MIN_QUEUE_SIZE) * MIN_QUEUE_SIZE; }
    };

    struct __attribute__((packed)) Header
    {
        message_id_t id      = {0};
        uint32_t     bodyLen = {0};
    };

    template <typename T>
    struct MessageTraits;

#define TYPE_MESSAGE_ID_BIND(type, messageId)                                                                          \
    namespace xncc::types {                                                                                            \
        template <>                                                                                                    \
        struct MessageTraits<type>                                                                                     \
        {                                                                                                              \
            static const message_id_t ID = messageId;                                                                  \
        };                                                                                                             \
    }

    using UserFunc = std::function<void(const char*, uint32_t, thread_id_t, connection_id_t)>;
}  // namespace types
}  // namespace xncc